package com.schoolcloud.social.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.schoolcloud.api.client.front.FrontUserClient;
import com.schoolcloud.common.model.R;
import com.schoolcloud.common.model.UserInfo;
import com.schoolcloud.common.model.PageDTO;
import com.schoolcloud.common.util.UserContext;
import com.schoolcloud.social.dto.SocEventCreateDTO;
import com.schoolcloud.social.entity.*;
import com.schoolcloud.social.enums.EventJoinStatus;
import com.schoolcloud.social.query.EventJoinerQuery;
import com.schoolcloud.social.query.EventParticipantsQuery;
import com.schoolcloud.social.query.EventQuery;
import com.schoolcloud.social.query.EventRemarkQuery;
import com.schoolcloud.social.service.*;
import com.schoolcloud.social.vo.EventDetailVO;
import com.schoolcloud.social.vo.EventJoinerVO;
import com.schoolcloud.social.vo.EventPersonInfoVO;
import com.schoolcloud.social.vo.EventReplyVO;
import com.schoolcolud.daomybatisplus.dto.MpPageUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class EventInteractionServiceImpl implements EventInteractionService {
    private final SocEventsService socEventsService;
    private final SocEveParReviewsService socEveParReviewsService;
    private final SocEventMienService eventMienService;
    private final SocEventConditionValuesService eventConditionValuesService;
    private final SocEventParticipantsService socEventParticipantsService;
    private final SocEventRemarkService eventRemarkService;
    private final FrontUserClient frontClient;
    private final EventCategoryService eventCategoryService;

    @Override
    public void addEvent(SocEventCreateDTO socEvent) {
        socEvent.setCreateTime(LocalDateTime.now());
        // 后台中可以直接设置组织者的id，而前台用户此字段应当为空
        if (socEvent.getOrganizerId() == null) {
            socEvent.setOrganizerId(Integer.valueOf(UserContext.getUser()));
        }
        socEventsService.save(socEvent);
        saveEventDetails(socEvent);
    }

    @Override
    public EventDetailVO getEventDetailById(Integer eventId) {
        EventDetailVO vo = new EventDetailVO();
        SocEvents byId = socEventsService.getById(eventId);
        if (byId == null) {
            return null;
        }
        BeanUtils.copyProperties(byId, vo);
//        封装发布者信息
        try {
            UserInfo user = frontClient.getFroUserInfoById(vo.getOrganizerId().toString()).getData();
            vo.setOrganizerAvatar(user.getAvatar());
        } catch (Exception e) {
            e.printStackTrace();
            log.info("用户不存在,异常:{}", e.getMessage());
        }
//        分类信息
        EventCategory category = eventCategoryService.getById(byId.getCategoryId());
        if (category != null) {
            vo.setCategoryName(category.getName());
        }
//        封装活动风采信息
        vo.setMienList(eventMienService.getEventListByEventId(String.valueOf(eventId)));
//        登录人是否参与
        try {
            Integer loginUser = UserContext.getUserToInteger();
            boolean exists = socEventParticipantsService.lambdaQuery()
                    .eq(SocEventParticipants::getEventId, eventId)
                    .eq(SocEventParticipants::getUserId, loginUser)
                    .eq(SocEventParticipants::getStatus, EventJoinStatus.APPROVED.getCode())
                    .exists();
            vo.setIsJoin(exists);
        } catch (Exception ignored) {
            log.info("没有登陆，无法判断当前用户是否参与");
        }
//        查询多少人参与
        Long joinerCount = socEventParticipantsService.getEventJoinerCount(eventId);
        vo.setJoinerCount(joinerCount);
        return vo;
    }

    @Override
    public void updateEvent(SocEventCreateDTO socEvent) {
        socEvent.setUpdateTime(LocalDateTime.now());
        socEventsService.updateById(socEvent);
        saveEventDetails(socEvent);
    }

    @Override
    public EventPersonInfoVO getEventPersonInfo(Integer userId) {
        EventPersonInfoVO vo = new EventPersonInfoVO();
        UserInfo froUserInfoById = frontClient.getFroUserInfoById(userId.toString()).getData();
        BeanUtils.copyProperties(froUserInfoById, vo);
//        统计用户发布的活动数和参与的活动数
        Long publishEventCount = socEventsService.getUserPublishEventCount(userId);
        vo.setPublishEventCount(publishEventCount);
        Long joinEventCount = socEventParticipantsService.getUserJoinEventCount(userId);
        vo.setJoinEventCount(joinEventCount);
        return vo;
    }

    @Override
    public PageDTO<EventDetailVO> getEventVOPage(EventQuery query) {
        String keywords = query.getKeywords();
        Integer categoryId = query.getCategoryId();
        String joinerId = query.getJoinerId();
        String organizationId = query.getOrganizationId();
        String sortBy = query.getSortByColumn();
        Integer status = query.getStatus();
        List<Integer> joinEventIds = null;
        if (StrUtil.isNotBlank(joinerId)) {
//            查询参与的活动
            List<SocEventParticipants> joinEventList = socEventParticipantsService.getUserJoinEvent(joinerId);
            joinEventIds = joinEventList.stream().map(SocEventParticipants::getEventId).collect(Collectors.toList());
            if (CollUtil.isEmpty(joinEventIds)) {
                return MpPageUtil.of(new Page<>(), EventDetailVO.class);
            }
        }
        Page<SocEvents> page = socEventsService.lambdaQuery()
                .eq(status != null, SocEvents::getStatus, status)
                .eq(categoryId != null && categoryId > 0, SocEvents::getCategoryId, categoryId)
                .like(StrUtil.isNotBlank(keywords), SocEvents::getTitle, keywords)
                .in(StrUtil.isNotBlank(joinerId), SocEvents::getEventId, joinEventIds)
                .eq(StrUtil.isNotBlank(organizationId), SocEvents::getOrganizerId, organizationId)
                .page(query.toMpPage());
        List<EventDetailVO> collect = page.getRecords().stream().map(item -> getEventDetailById(item.getEventId())).collect(Collectors.toList());
        PageDTO<EventDetailVO> of = MpPageUtil.of(page, EventDetailVO.class);
        of.setList(collect);
        return of;
    }

    @Override
    public void userJoinEvent(SocEventParticipants socEventParticipants) {
//        先查询活动是否需要审核
        SocEvents byId = socEventsService.getById(socEventParticipants.getEventId());
        if (byId.getRequiresApproval() == 0) {
            socEventParticipants.setStatus(EventJoinStatus.APPROVED.getCode());//通过
        } else socEventParticipants.setStatus(EventJoinStatus.WAIT_REVIEW.getCode());
        socEventParticipants.setAppliedTime(LocalDateTime.now());
        if (!UserContext.getIsAdmin()) {
            socEventParticipants.setUserId(UserContext.getUserToInteger());
        }
        socEventParticipantsService.save(socEventParticipants);
    }

    @Override
    public PageDTO<SocEventParticipants> getEventParticipantPage(EventParticipantsQuery eventParticipantsQuery) {
        Integer eventId = eventParticipantsQuery.getEventId();
        Integer eventUserId = eventParticipantsQuery.getEventUserId();
        List<Integer> publishEventIds = null;
        if (eventUserId != null) {
//            查询用户发布的活动
            publishEventIds = socEventsService.lambdaQuery().eq(SocEvents::getOrganizerId, eventUserId).list().stream().map(SocEvents::getEventId).collect(Collectors.toList());
        }
        Page<SocEventParticipants> page = socEventParticipantsService.lambdaQuery()
                .eq(eventId != null, SocEventParticipants::getEventId, eventId)
                .in(CollUtil.isNotEmpty(publishEventIds), SocEventParticipants::getEventId, publishEventIds)
                .page(eventParticipantsQuery.toMpPage());
        return null;
    }

    @Override
    public PageDTO<EventJoinerVO> getEventJoinerPage(EventJoinerQuery query) {
        Integer eventId = query.getEventId();
        Page<SocEventParticipants> page = socEventParticipantsService.lambdaQuery()
                .eq(eventId!=null,SocEventParticipants::getEventId, eventId).page(query.toMpPage());
        List<EventJoinerVO> collect = page.getRecords().stream().map(item -> {
            EventJoinerVO eventJoinerVO = new EventJoinerVO();
            UserInfo data = frontClient.getFroUserInfoById(item.getUserId().toString()).getData();
            BeanUtils.copyProperties(data, eventJoinerVO);
            eventJoinerVO.setJoinTime(item.getAppliedTime());//todo 这里只是申请时间
            return eventJoinerVO;
        }).collect(Collectors.toList());
        PageDTO<EventJoinerVO> of = MpPageUtil.of(page, EventJoinerVO.class);
        of.setList(collect);
        return of;
    }

    @Override
    public PageDTO<EventReplyVO> getEventRemarkPage(EventRemarkQuery query) {
        Integer parentId = query.getParentId();
        Page<SocEventRemark> page = eventRemarkService.lambdaQuery()
                .eq(SocEventRemark::getEventId, query.getEventId())
                .eq(parentId==null,SocEventRemark::getParentId, 0)
                .eq(parentId != null, SocEventRemark::getParentId, parentId)
                .page(query.toMpPage());
        PageDTO<EventReplyVO> of = MpPageUtil.of(page, EventReplyVO.class);
        if (CollUtil.isNotEmpty(of.getList())){
            of.getList().forEach(item -> {
                R<UserInfo> froUserInfoById = frontClient.getFroUserInfoById(item.getUserId().toString());
                UserInfo data = froUserInfoById.getData();
                item.setAvatar(data.getAvatar());
                item.setNickname(data.getNickname());
            });
        }
        return of;
    }

    private void saveEventDetails(SocEventCreateDTO socEvent) {
        List<SocEventConditionValues> conditions = socEvent.getConditions();
        List<SocEventMien> miens = socEvent.getMiens();
        // 保存参与条件
        if (CollUtil.isNotEmpty(conditions)) {
            for (SocEventConditionValues condition : conditions) {
                condition.setEventId(socEvent.getEventId());
                eventConditionValuesService.save(condition);
            }
        }
        // 保存活动风采信息
        if (CollUtil.isNotEmpty(miens)) {
//            先删除之前的风采信息，再执行插入
            eventMienService.removeByEventId(socEvent.getEventId().toString());
            for (SocEventMien mien : miens) {
                mien.setEventId(socEvent.getEventId());
                eventMienService.save(mien);
            }
        }
    }
}
